home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Extensions / Imaging / PIL / WmfImagePlugin.py < prev    next >
Encoding:
Text File  |  2000-06-23  |  6.2 KB  |  280 lines

  1. #
  2. # THIS IS WORK IN PROGRESS.
  3. #
  4. # The Python Imaging Library.
  5. # $Id: WmfImagePlugin.py,v 1.1.1.2 1999/01/13 09:39:53 sjoerd Exp $
  6. #
  7. # WMF support for PIL
  8. #
  9. # history:
  10. #    96-12-14 fl    Created
  11. #
  12. # notes:
  13. #    This code currently supports placable metafiles only, and
  14. #    just a few graphics operations are implemented.
  15. #
  16. # Copyright (c) Secret Labs AB 1997.
  17. # Copyright (c) Fredrik Lundh 1996.
  18. #
  19. # See the README file for information on usage and redistribution.
  20. #
  21.  
  22. __version__ = "0.1"
  23.  
  24. import Image, ImageDraw, ImageFile
  25. import string
  26.  
  27. #
  28. # --------------------------------------------------------------------
  29.  
  30. def i16(c):
  31.     return ord(c[0]) + (ord(c[1])<<8)
  32.  
  33. def i32(c):
  34.     return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
  35.  
  36. # --------------------------------------------------------------------
  37. # The following codes are taken from the wingdi.h header file.
  38. # Copyright (c) 1985-1996, Microsoft Corp.  All rights reserved.
  39.  
  40. META_ANIMATEPALETTE = 0x0436
  41. META_ARC = 0x0817
  42. META_BITBLT = 0x0922
  43. META_CHORD = 0x0830
  44. META_CREATEBRUSHINDIRECT = 0x02FC
  45. META_CREATEFONTINDIRECT = 0x02FB
  46. META_CREATEPALETTE = 0x00f7
  47. META_CREATEPATTERNBRUSH = 0x01F9
  48. META_CREATEPENINDIRECT = 0x02FA
  49. META_CREATEREGION = 0x06FF
  50. META_DELETEOBJECT = 0x01f0
  51. META_DIBBITBLT = 0x0940
  52. META_DIBCREATEPATTERNBRUSH = 0x0142
  53. META_DIBSTRETCHBLT = 0x0b41
  54. META_ELLIPSE = 0x0418
  55. META_ESCAPE = 0x0626
  56. META_EXCLUDECLIPRECT = 0x0415
  57. META_EXTFLOODFILL = 0x0548
  58. META_EXTTEXTOUT = 0x0a32
  59. META_FILLREGION = 0x0228
  60. META_FLOODFILL = 0x0419
  61. META_FRAMEREGION = 0x0429
  62. META_INTERSECTCLIPRECT = 0x0416
  63. META_INVERTREGION = 0x012A
  64. META_LINETO = 0x0213
  65. META_MOVETO = 0x0214
  66. META_OFFSETCLIPRGN = 0x0220
  67. META_OFFSETVIEWPORTORG = 0x0211
  68. META_OFFSETWINDOWORG = 0x020F
  69. META_PAINTREGION = 0x012B
  70. META_PATBLT = 0x061D
  71. META_PIE = 0x081A
  72. META_POLYGON = 0x0324
  73. META_POLYLINE = 0x0325
  74. META_POLYPOLYGON = 0x0538
  75. META_REALIZEPALETTE = 0x0035
  76. META_RECTANGLE = 0x041B
  77. META_RESIZEPALETTE = 0x0139
  78. META_RESTOREDC = 0x0127
  79. META_ROUNDRECT = 0x061C
  80. META_SAVEDC = 0x001E
  81. META_SCALEVIEWPORTEXT = 0x0412
  82. META_SCALEWINDOWEXT = 0x0410
  83. META_SELECTCLIPREGION = 0x012C
  84. META_SELECTOBJECT = 0x012D
  85. META_SELECTPALETTE = 0x0234
  86. META_SETBKCOLOR = 0x0201
  87. META_SETBKMODE = 0x0102
  88. META_SETDIBTODEV = 0x0d33
  89. META_SETMAPMODE = 0x0103
  90. META_SETMAPPERFLAGS = 0x0231
  91. META_SETPALENTRIES = 0x0037
  92. META_SETPIXEL = 0x041F
  93. META_SETPOLYFILLMODE = 0x0106
  94. META_SETRELABS = 0x0105
  95. META_SETROP2 = 0x0104
  96. META_SETSTRETCHBLTMODE = 0x0107
  97. META_SETTEXTALIGN = 0x012E
  98. META_SETTEXTCHAREXTRA = 0x0108
  99. META_SETTEXTCOLOR = 0x0209
  100. META_SETTEXTJUSTIFICATION = 0x020A
  101. META_SETVIEWPORTEXT = 0x020E
  102. META_SETVIEWPORTORG = 0x020D
  103. META_SETWINDOWEXT = 0x020C
  104. META_SETWINDOWORG = 0x020B
  105. META_STRETCHBLT = 0x0B23
  106. META_STRETCHDIB = 0x0f43
  107. META_TEXTOUT = 0x0521
  108.  
  109. # create a code to name dictionary (for debugging)
  110. NAME = {}
  111. for k, v in vars().items():
  112.     if k[:5] == "META_":
  113.     NAME[v] = k[5:]
  114.  
  115. #
  116. # --------------------------------------------------------------------
  117. # Read WMF file
  118.  
  119. def _accept(prefix):
  120.     return prefix[:6] == "\327\315\306\232\000\000"
  121.  
  122. class WmfImageFile(ImageFile.ImageFile):
  123.  
  124.     format = "WMF"
  125.     format_description = "Windows Metafile"
  126.  
  127.     def _open(self):
  128.  
  129.     # check placable header
  130.     s = self.fp.read(22)
  131.     if s[:6] != "\327\315\306\232\000\000":
  132.         raise SyntaxError, "Not a placable WMF file"
  133.  
  134.     # position on output device
  135.     bbox = i16(s[6:8]), i16(s[8:10]), i16(s[10:12]), i16(s[12:14])
  136.  
  137.     # FIXME: should take the scale into account
  138.  
  139.     self.mode = "P"
  140.     self.size = (bbox[2]-bbox[0]) / 20, (bbox[3]-bbox[1]) / 20
  141.  
  142.     # FIXME: while hacking
  143.     self.size = (bbox[2] + bbox[0])/10, (bbox[3] + bbox[1])/10
  144.  
  145.     self.bbox = bbox
  146.  
  147.     # check standard header
  148.     s = self.fp.read(18)
  149.     if s[:6] != "\001\000\011\000\000\003":
  150.         raise SyntaxError, "Not a WMF file"
  151.  
  152.     def _ink(self, rgb):
  153.  
  154.     # lookup colour in current palette
  155.     try:
  156.         return self.palette[rgb]
  157.     except KeyError:
  158.         # hmm. what if the palette becomes full?
  159.         ink = len(self.palette)
  160.         self.palette[rgb] = ink
  161.         return ink
  162.  
  163.     def load(self, modify=0):
  164.  
  165.     if self.im:
  166.         return
  167.  
  168.     #
  169.     # windows standard palette
  170.  
  171.     self.palette = {
  172.         '\000\000\000': 0,
  173.         '\200\000\000': 1,
  174.         '\000\200\000': 2,
  175.         '\200\200\000': 3,
  176.         '\000\000\200': 4,
  177.         '\200\000\200': 5,
  178.         '\000\200\200': 6,
  179.         '\300\300\300': 7,
  180.         '\300\334\300': 8,
  181.         '\246\312\360': 9,
  182.         '\377\373\360': 246,
  183.         '\240\240\244': 247,
  184.         '\200\200\200': 248,
  185.         '\377\000\000': 249,
  186.         '\000\377\000': 250,
  187.         '\377\377\000': 251,
  188.         '\000\000\377': 252,
  189.         '\377\000\377': 253,
  190.         '\000\377\377': 254,
  191.         '\377\377\377': 255,
  192.     }
  193.  
  194.     fill = 0
  195.  
  196.     pen = brush = self._ink("\000\000\000")
  197.     paper = self._ink("\377\377\377")
  198.  
  199.     self.im = Image.core.fill(self.mode, self.size, paper)
  200.  
  201.     #
  202.     # render metafile into image, using the standard palette
  203.  
  204.     id = ImageDraw.ImageDraw(self)
  205.  
  206.     while 1:
  207.  
  208.         s = self.fp.read(6)
  209.  
  210.         size = i32(s)*2
  211.         func = i16(s[4:])
  212.  
  213.         if not func:
  214.         break
  215.  
  216.         s = self.fp.read(size-6)
  217.  
  218.         if func == META_SETPOLYFILLMODE:
  219.         fill = i16(s)
  220.         id.setfill(fill)
  221.  
  222.         elif func == META_CREATEBRUSHINDIRECT:
  223.         brush = self._ink(s[2:5])
  224.  
  225.         elif func == META_CREATEPENINDIRECT:
  226.         pen = self._ink(s[6:9])
  227.  
  228.         elif func == META_POLYGON:
  229.         xy = map(lambda i,s=s: i16(s[i:i+2])/10, range(2, len(s), 2))
  230.         if fill:
  231.             id.setink(brush)
  232.             id.polygon(xy)
  233.             id.setink(pen)
  234.             id.setfill(0)
  235.             id.polygon(xy)
  236.             id.setfill(1)
  237.         else:
  238.             id.setink(pen)
  239.             id.polygon(xy)
  240.  
  241.         elif func == META_POLYLINE:
  242.         xy = map(lambda i,s=s: i16(s[i:i+2])/10, range(2, len(s), 2))
  243.         id.setink(pen)
  244.         id.line(xy)
  245.  
  246.         elif func == META_RECTANGLE:
  247.         xy = (i16(s[2:4])/10, i16(s[0:2])/10,
  248.               i16(s[6:8])/10, i16(s[4:6])/10)
  249.         if fill:
  250.             id.setink(brush)
  251.             id.rectangle(xy)
  252.             id.setink(pen)
  253.             id.setfill(0)
  254.             id.rectangle(xy)
  255.             id.setfill(1)
  256.         else:
  257.             id.setink(pen)
  258.             id.rectangle(xy)
  259.         else:
  260.         if Image.DEBUG:
  261.             print size, hex(func), NAME[func]
  262.         pass
  263.  
  264.     #
  265.     # attach palette to image
  266.  
  267.     palette = ["\0\0\0"] * 256
  268.     for rgb, i in self.palette.items():
  269.         if i < 256:
  270.         palette[i] = rgb
  271.     self.im.putpalette("RGB", string.join(palette, ""))
  272.  
  273. #
  274. # --------------------------------------------------------------------
  275. # Registry stuff
  276.  
  277. Image.register_open("WMF", WmfImageFile, _accept)
  278.  
  279. Image.register_extension("WMF", ".wmf")
  280.